package top.codedance.iotp.common.util;

import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;

public class ByteUtils {
    /**
     * 大端字节转小端字节
     * @param beInt
     * @return
     */
    public static byte BeToLe(byte beInt){
        ByteBuffer buffer = ByteBuffer.allocate(1);
        buffer.order(ByteOrder.BIG_ENDIAN);
        buffer.put(beInt);
        buffer.order(ByteOrder.LITTLE_ENDIAN);
        return buffer.get(0);
    }

    /**
     * 大端字节转小端字节
     * @param beInt
     * @return
     */
    public static short BeToLe(short beInt){
        ByteBuffer buffer = ByteBuffer.allocate(2);
        buffer.order(ByteOrder.BIG_ENDIAN);
        buffer.putShort(beInt);
        buffer.order(ByteOrder.LITTLE_ENDIAN);
        return buffer.getShort(0);
    }

    /**
     * 大端字节转小端字节
     * @param beInt
     * @return
     */
    public static int BeToLe(int beInt){
        ByteBuffer buffer = ByteBuffer.allocate(4);
        buffer.order(ByteOrder.BIG_ENDIAN);
        buffer.putInt(beInt);
        buffer.order(ByteOrder.LITTLE_ENDIAN);
        return buffer.getInt(0);
    }

    /**
     * 大端字节转小端字节
     * @param beInt
     * @return
     */
    public static long BeToLe(long beInt){
        ByteBuffer buffer = ByteBuffer.allocate(8);
        buffer.order(ByteOrder.BIG_ENDIAN);
        buffer.putLong(beInt);
        buffer.order(ByteOrder.LITTLE_ENDIAN);
        return buffer.getLong(0);
    }

    /**
     * 大端字节转小端字节
     * @param beBigInteger
     * @return
     */
    public static BigInteger BeToLe(BigInteger beBigInteger){
        long l = beBigInteger.longValue();
        ByteBuffer buffer = ByteBuffer.allocate(8);
        buffer.order(ByteOrder.BIG_ENDIAN);
        buffer.putLong(l);
        buffer.order(ByteOrder.LITTLE_ENDIAN);
        return BigInteger.valueOf(buffer.getLong(0));
    }

    /**
     * 大端字节转小端字节
     * @param beInt
     * @return
     */
    public static float BeToLe(float beInt){
        ByteBuffer buffer = ByteBuffer.allocate(4);
        buffer.order(ByteOrder.BIG_ENDIAN);
        buffer.putFloat(beInt);
        buffer.order(ByteOrder.LITTLE_ENDIAN);
        return buffer.getFloat(0);
    }

    /**
     * 大端字节转小端字节
     * @param beInt
     * @return
     */
    public static double BeToLe(double beInt){
        ByteBuffer buffer = ByteBuffer.allocate(8);
        buffer.order(ByteOrder.BIG_ENDIAN);
        buffer.putDouble(beInt);
        buffer.order(ByteOrder.LITTLE_ENDIAN);
        return buffer.getDouble(0);
    }

    /**
     * 小端字节转大端字节
     * @param leInt
     * @return
     */
    public static byte LeToBe(byte leInt){
        ByteBuffer buffer = ByteBuffer.allocate(1);
        buffer.order(ByteOrder.LITTLE_ENDIAN);
        buffer.put(leInt);
        buffer.order(ByteOrder.BIG_ENDIAN);
        return buffer.get(0);
    }

    /**
     * 小端字节转大端字节
     * @param leInt
     * @return
     */
    public static short LeToBe(short leInt){
        ByteBuffer buffer = ByteBuffer.allocate(2);
        buffer.order(ByteOrder.LITTLE_ENDIAN);
        buffer.putShort(leInt);
        buffer.order(ByteOrder.BIG_ENDIAN);
        return buffer.getShort(0);
    }

    /**
     * 小端字节转大端字节
     * @param leInt
     * @return
     */
    public static int LeToBe(int leInt){
        ByteBuffer buffer = ByteBuffer.allocate(4);
        buffer.order(ByteOrder.LITTLE_ENDIAN);
        buffer.putInt(leInt);
        buffer.order(ByteOrder.BIG_ENDIAN);
        return buffer.getInt(0);
    }

    /**
     * 小端字节转大端字节
     * @param leInt
     * @return
     */
    public static long LeToBe(long leInt){
        ByteBuffer buffer = ByteBuffer.allocate(8);
        buffer.order(ByteOrder.LITTLE_ENDIAN);
        buffer.putLong(leInt);
        buffer.order(ByteOrder.BIG_ENDIAN);
        return buffer.getLong(0);
    }

    /**
     * 小端字节转大端字节
     * @param leBigInteger
     * @return
     */
    public static BigInteger LeToBe(BigInteger leBigInteger){
        long l = leBigInteger.longValue();
        ByteBuffer buffer = ByteBuffer.allocate(8);
        buffer.order(ByteOrder.LITTLE_ENDIAN);
        buffer.putLong(l);
        buffer.order(ByteOrder.BIG_ENDIAN);
        return BigInteger.valueOf(buffer.getLong(0));
    }

    /**
     * 小端字节转大端字节
     * @param leInt
     * @return
     */
    public static float LeToBe(float leInt){
        ByteBuffer buffer = ByteBuffer.allocate(4);
        buffer.order(ByteOrder.LITTLE_ENDIAN);
        buffer.putFloat(leInt);
        buffer.order(ByteOrder.BIG_ENDIAN);
        return buffer.getFloat(0);
    }

    /**
     * 小端字节转大端字节
     * @param leInt
     * @return
     */
    public static double LeToBe(double leInt){
        ByteBuffer buffer = ByteBuffer.allocate(8);
        buffer.order(ByteOrder.LITTLE_ENDIAN);
        buffer.putDouble(leInt);
        buffer.order(ByteOrder.BIG_ENDIAN);
        return buffer.getDouble(0);
    }

    /**
     *
     * @param v
     * @return
     */
    public static short swap(short v){
        ByteBuffer buffer = ByteBuffer.allocate(2);
        buffer.putShort(v);
        byte[] array = buffer.array();
        byte[] newArr = new byte[array.length];
        for (int i = 0; i < array.length - 1; i+=2) {
            newArr[i] = array[i+1];
            newArr[i+1] = array[i];
        }
        return ByteBuffer.wrap(newArr).getShort();
    }

    /**
     *
     * @param v
     * @return
     */
    public static int swap(int v){
        ByteBuffer buffer = ByteBuffer.allocate(4);
        buffer.putInt(v);
        byte[] array = buffer.array();
        byte[] newArr = new byte[array.length];
        for (int i = 0; i < array.length - 1; i+=2) {
            newArr[i] = array[i+1];
            newArr[i+1] = array[i];
        }
        return ByteBuffer.wrap(newArr).getInt();
    }

    /**
     *
     * @param v
     * @return
     */
    public static long swap(long v){
        ByteBuffer buffer = ByteBuffer.allocate(8);
        buffer.putLong(v);
        byte[] array = buffer.array();
        byte[] newArr = new byte[array.length];
        for (int i = 0; i < array.length - 1; i+=2) {
            newArr[i] = array[i+1];
            newArr[i+1] = array[i];
        }
        return ByteBuffer.wrap(newArr).getLong();
    }

    /**
     *
     * @param v
     * @return
     */
    public static float swap(float v){
        ByteBuffer buffer = ByteBuffer.allocate(4);
        buffer.putFloat(v);
        byte[] array = buffer.array();
        byte[] newArr = new byte[array.length];
        for (int i = 0; i < array.length - 1; i+=2) {
            newArr[i] = array[i+1];
            newArr[i+1] = array[i];
        }
        return ByteBuffer.wrap(newArr).getFloat();
    }

    /**
     *
     * @param v
     * @return
     */
    public static double swap(double v){
        ByteBuffer buffer = ByteBuffer.allocate(8);
        buffer.putDouble(v);
        byte[] array = buffer.array();
        byte[] newArr = new byte[array.length];
        for (int i = 0; i < array.length - 1; i+=2) {
            newArr[i] = array[i+1];
            newArr[i+1] = array[i];
        }
        return ByteBuffer.wrap(newArr).getDouble();
    }

    /**
     *
     * @param v
     * @return
     */
    public static BigInteger swap(BigInteger v){
        return BigInteger.valueOf(swap(v.longValue()));
    }

    /**
     *
     * @param v
     * @return
     */
    public static byte toUnsigned(short v){
        ByteBuffer buffer = ByteBuffer.allocate(2);
        buffer.putInt(v);
        byte[] array = buffer.array();
        byte[] newArr = new byte[1];
        int z = 0;
        for (int i = 1; i < 2; i++) {
            newArr[z] = array[i];
            z++;
        }
        return ByteBuffer.wrap(newArr).get();
    }

    /**
     *
     * @param v
     * @return
     */
    public static short toUnsigned(int v){
        ByteBuffer buffer = ByteBuffer.allocate(4);
        buffer.putInt(v);
        byte[] array = buffer.array();
        byte[] newArr = new byte[2];
        int z = 0;
        for (int i = 2; i < 4; i++) {
            newArr[z] = array[i];
            z++;
        }
        return ByteBuffer.wrap(newArr).getShort();
    }

    /**
     *
     * @param v
     * @return
     */
    public static int toUnsigned(long v){
        ByteBuffer buffer = ByteBuffer.allocate(8);
        buffer.putLong(v);
        byte[] array = buffer.array();
        byte[] newArr = new byte[4];
        int z = 0;
        for (int i = 4; i < 8; i++) {
            newArr[z] = array[i];
            z++;
        }
        return ByteBuffer.wrap(newArr).getInt();
    }

    /**
     *
     * @param v
     * @return
     */
    public static long toUnsigned(BigInteger v){
        return v.longValueExact();
    }
}
